#include<iostream>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include"task.hpp"

enum
{
    OK=0,
    USSAGEERROR,
    CREATEERROR,
    PIPEERROR
};
TaskManager task;

class ProcessPool
{
public:
    ProcessPool(pid_t id,int fd):_id(id),_wfd(fd)
    {
        _name="subprocess-"+std::to_string(id)+'-'+std::to_string(fd);
    }

    int getwfd()
    {
        return _wfd;
    }

    int getpid()
    {
        return _id;
    }

    ~ProcessPool()
    {}
private:
    pid_t _id;
    int _wfd;
    std::string _name;
};

using proc_t=ProcessPool;

void ExecuteTask(int code)
{
    std::cout<<getpid()<<":";
    task.ExecuteTask(code);
}

void  work()
{
    int task_code;
    while(true)
    {
        read(0,&task_code,sizeof(task_code));//将管道发送的任务码进行读取。
        ExecuteTask(task_code);
        sleep(1);
    }
}

int CreateProcessPool(std::vector<proc_t>& tm , int num)
{
    while(num--)
    {
        int pfd[2];
        int ret=pipe(pfd);
        if(ret==-1)
        {
            return PIPEERROR; 
        }

        pid_t id=fork();
        if(id==0)
        {
            //子进程执行
            close(pfd[1]);//子进程关闭写端
            dup2(pfd[0],0);//将标准输入流改为读端
            work();
            exit(0);
        }
        else if(id>0)
        {
            //父进程执行
            close(pfd[0]);//父进程关闭读端
            tm.push_back(proc_t(id,pfd[1]));
        }
        else if(id<0)
        {
            //创建失败
            return CREATEERROR;
        }
    }
    return OK;
}
void CloseProcesspool(std::vector<proc_t>& task_manager)
{
    for(auto& e:task_manager)
    {
        std::cout<<"close pid:"<<e.getpid()<<"fd:"<<e.getwfd();
        close(e.getwfd());
        waitpid(e.getpid(),nullptr,0);
    }
}
void ussage()
{
    std::cout<<"Ussage: ./processpool N"<<std::endl;
}

void AssignTask(std::vector<proc_t>& tm,int & who)//分配任务
{
    srand(time(nullptr));
    int taskcode=rand()%3;
    
    std::cout<<tm[who].getpid()<<"-"<<tm[who].getwfd()<<std::endl;
    write(tm[who].getwfd(),&taskcode,sizeof(taskcode));//将任务码通过管道写给子进程
    sleep(1);
}

int main(int argc,char* argv[])
{
    std::vector<proc_t> task_manager;

    if(argc!=2)
    {
        ussage();
        return USSAGEERROR;
    }

    int who=0;
    int num=std::stoi(argv[1]);
    int task_time=20;
    CreateProcessPool(task_manager,num);
    while(task_time--)
    {
        std::cout<<task_time<<std::endl;
        AssignTask(task_manager,who);
        who++;
        who%=num;
    }
    std::cout<<"close start"<<std::endl;
    CloseProcesspool(task_manager);
    std::cout<<"ending"<<std::endl;
    return 0;
}